#!/usr/bin/env python3
import sys
import re
import html
import asyncio as aio
from itertools import cycle
from urllib import parse

import aiohttp as ahttp

apikey = 'EABB82DCE066D8062F7692D133A7A711'
# regex used in api visit
pat2 = re.compile('<pos>(.*?)</pos>.*?<acceptation>(.*?)</acceptation>', re.S)

@aio.coroutine
async def spin(word):
    write, flush = sys.stdout.write, sys.stdout.flush
    msg_base = 'Getting "%s": '%word
    write(msg_base)
    for c in cycle('|/-\\'):
        write(c)
        flush()
        write('\b')
        try:
            await aio.sleep(0.1)
        except aio.CancelledError:
            break
    length = len(msg_base)
    write('\b'*length + ' '*(length+1) + '\b'*(length+1))

@aio.coroutine
async def connect_and_getdata(url):
    async with ahttp.request('GET', url) as resp:
        if resp.status == 200:
            page = await resp.read()
            return page.decode('utf-8')
        else:
            raise ahttp.HttpProcessingError(
                code=resp.status, message=resp.reason,
                headers=resp.headers)

@aio.coroutine
async def connect_and_getdata_fake(url):
    await aio.sleep(3.)
    raise RuntimeError()

@aio.coroutine
async def search_word_api(word):
    spinner = aio.ensure_future(spin(word))
    if not word:
        raise IOError('Invalid word: %s!' % word)
    keywords = {'w': word, 'key': apikey}
    url = 'http://dict-co.iciba.com/api/dictionary.php?' + parse.urlencode(keywords)
    try:
        page = await connect_and_getdata(url)
    except Exception:
        return word, None
    finally:
        spinner.cancel()

    myitem = pat2.findall(page)
    if myitem:
        meanings = []
        for it in myitem:
            wt = it[0]
            mn = it[1].strip()
            meanings.append((wt, mn))
    else:
        meanings = None
    return word, meanings

def print_meanings(word, meanings):
    if meanings:
        print("\033[1;31m%s:\033[0m"%word)
        for it in meanings:
            wt, mn = it
            if wt:
                print('\033[1;34m%s\033[0m %s' % (wt, html.unescape(mn)))
            else:
                print(html.unescape(mn))
    else:
        print('Do not find "\033[1;31m%s\033[0m"!' %word)

def search_word_cli(word):
    loop = aio.get_event_loop() # 获取事件循环的引用
    result = loop.run_until_complete(search_word_api(word)) # 驱动supervisor协程, 让它运行完毕，获得这次调用的返回值
    loop.close()
    print_meanings(*result)

if __name__ == '__main__':
    word = ' '.join(sys.argv[1:])
    search_word_cli(word)